<template>
    <div id="tags-view-container" class="tags-view-container">
      <div ref="tabScrollbarRef" class="tags-view-wrapper" @wheel.prevent="handleScroll">
        <router-link
          v-for="tag in visitedViews"
          :key="tag.path"
          :data-path="tag.path"
          :class="isActive(tag) ? 'active' : ''"
          :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
          class="tags-view-item"
          :style="activeStyle(tag)"
          @click.middle="!isAffix(tag) ? closeSelectedTag(tag) : ''"
          @contextmenu.prevent="openMenu(tag, $event)"
        >
          {{ tag.title }}
          <span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
            <close class="el-icon-close" style="width: 1em; height: 1em;vertical-align: middle;" />
          </span>
        </router-link>
        </div>
      <ul v-show="visible" :style="{ left: left + 'px', top: top + 'px' }" class="contextmenu">
        <li @click="refreshSelectedTag(selectedTag)">
          <refresh-right style="width: 1em; height: 1em;" /> 刷新页面
        </li>
        <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">
          <close style="width: 1em; height: 1em;" /> 关闭当前
        </li>
        <li @click="closeOthersTags">
          <circle-close style="width: 1em; height: 1em;" /> 关闭其他
        </li>
        <li v-if="!isFirstView()" @click="closeLeftTags">
          <back style="width: 1em; height: 1em;" /> 关闭左侧
        </li>
        <li v-if="!isLastView()" @click="closeRightTags">
          <right style="width: 1em; height: 1em;" /> 关闭右侧
        </li>
        <li @click="closeAllTags(selectedTag)">
          <circle-close style="width: 1em; height: 1em;" /> 全部关闭
        </li>
      </ul>
    </div>
  </template>
  
<script setup lang="ts">
import { getNormalPath } from '/@/utils/common'
import { useClient } from '/@/stores/client'
import { useTagsView } from '/@/stores/tagsView'
import { useUserSettings } from '/@/stores/userSettings'
import { computed, nextTick, onMounted, ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router'
import { useUserViews } from '/@/stores/userViews'
import horizontalScroll from '/@/utils/horizontalScroll'
import tag from '/@/utils/tag'
import variables from "/@/assets/styles/variables.module.scss"

const visible = ref(false)
const top = ref(0)
const left = ref(0)
const selectedTag = ref({})
const affixTags = ref([])
const tabScrollbarRef = ref()

const route = useRoute()
const router = useRouter()
const client = useClient()
  
const visitedViews = computed(() => useTagsView().visitedViews)
const routes = computed(() => useUserViews().routes)
const themeColor = computed(() => useUserSettings().themeColor)
const sidebar = computed(() => client.sidebar)
const tagVisible = computed(() => useUserSettings().tagsView)
watch(route, () => {
    addTags()
    moveToCurrentTag()
})
watch(visible, (value) => {
    if (value) {
        document.body.addEventListener('click', closeMenu)
    } else {
        document.body.removeEventListener('click', closeMenu)
    }
})
onMounted(() => {
    initTags()
    addTags()
    new horizontalScroll(tabScrollbarRef.value)
})

function isActive(r:any) {
    if (route.path && route.path.indexOf(r.path) === 0) {
        return true
    }
}
function activeStyle(tag:any) {
    if (!isActive(tag)) return {};
    return {
        "background-color": themeColor.value,
        "border-color": themeColor.value
    };
}
function isAffix(tag:any) {
    return tag.meta && tag.meta.affix
}
function isFirstView() {
    try {
        return selectedTag.value.fullPath === visitedViews.value[1].fullPath || selectedTag.value.fullPath === '/index'
    } catch (err) {
        return false
    }
}
function isLastView() {
    try {
        return selectedTag.value.fullPath === visitedViews.value[visitedViews.value.length - 1].fullPath
    } catch (err) {
        return false
    }
}
function filterAffixTags(routes: any, basePath = '') {
    let tags: any[] = []
    routes.forEach((route:any) => {
        if (route.meta && route.meta.affix) {
            const tagPath = getNormalPath(route.path)
            tags.push({
                fullPath: tagPath,
                path: tagPath,
                name: route.name,
                meta: { ...route.meta }
            })
        }
        if (route.children) {
            const tempTags = filterAffixTags(route.children, route.path)
            if (tempTags.length >= 1) {
                tags = [...tags, ...tempTags]
            }
        }
    })
    return tags
}
function initTags() {
    if(!tagVisible.value) return
    const res = filterAffixTags(routes.value);
    affixTags.value = res;
    for (const tag of res) {
        // Must have tag name
        if (tag.name) {
            useTagsView().addVisitedView(tag)
        }
    }
}
function addTags() {
    if(!tagVisible.value) return
    const { name } = route
    if (name) {
        useTagsView().addView(route)
        if (route.meta.link) {
            useTagsView().addIframeView(route);
        }
    }
    return false
}
function moveToCurrentTag() {
    nextTick(() => {
        for (const r of visitedViews.value) {
            if (r.path === route.path) {
                // when query is different then update
                if (r.fullPath !== route.fullPath) {
                    useTagsView().updateVisitedView(route)
                }
            }
        }
    })
}
function refreshSelectedTag(view: any) {
    tag.refreshPage(view);
    if (route.meta.link) {
        useTagsView().delIframeView(route);
    }
}
function closeSelectedTag(view: any) {
    tag.closePage(view).then(({ visitedViews }) => {
        if (isActive(view)) {
            toLastView(visitedViews, view)
        }
    })
}
function closeRightTags() {
    tag.closeRightPage(selectedTag.value).then(visitedViews => {
        if (!visitedViews.find(i => i.fullPath === route.fullPath)) {
            toLastView(visitedViews)
        }
    })
}
function closeLeftTags() {
    tag.closeLeftPage(selectedTag.value).then(visitedViews => {
        if (!visitedViews.find(i => i.fullPath === route.fullPath)) {
            toLastView(visitedViews)
        }
    })
}
function closeOthersTags() {
    router.push(selectedTag.value).catch(() => { });
    tag.closeOtherPage(selectedTag.value).then(() => {
        moveToCurrentTag()
    })
}
function closeAllTags(view: any) {
    tag.closeAllPage().then(({ visitedViews }) => {
        if (affixTags.value.some(tag => tag.path === route.path)) {
            return
        }
        toLastView(visitedViews, view)
    })
}
function toLastView(visitedViews, view) {
    const latestView = visitedViews.slice(-1)[0]
    if (latestView) {
        router.push(latestView.path)
    } else {
        if (view.path === '/platform/dashboard') {
            router.replace({ path: '/redirect' + view.fullPath })
        } else {
            router.push('/')
        }
    }
}
function openMenu(tag, e) {
    let leftWidth = parseInt(variables.sideBarWidth)
    if(!sidebar.value.opened){
        leftWidth = 54
    }
    const { clientX, clientY } = e
    const maxLeft = clientX - leftWidth // left boundary
    const l = e.clientX - leftWidth + 15 // 15: margin right
  
    if (l > maxLeft) {
        left.value = maxLeft
    } else {
        left.value = l
    }
  
    top.value = e.clientY
    visible.value = true
    selectedTag.value = tag
}
function closeMenu() {
    visible.value = false
}
function handleScroll() {
    closeMenu()
}
</script>
  
  <style lang='scss' scoped>
  .tags-view-container {
    height: 34px;
    width: 100%;
    background: #fff;
    border-bottom: 1px solid #d8dce5;
    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 0 3px 0 rgba(0, 0, 0, 0.04);
    .tags-view-wrapper {
      .tags-view-item {
        display: inline-block;
        position: relative;
        cursor: pointer;
        height: 26px;
        line-height: 26px;
        border: 1px solid #d8dce5;
        color: #495060;
        background: #fff;
        padding: 0 8px;
        font-size: 12px;
        margin-left: 5px;
        margin-top: 4px;
        &:first-of-type {
          margin-left: 15px;
        }
        &:last-of-type {
          margin-right: 15px;
        }
        &.active {
          background-color: #42b983;
          color: #fff;
          border-color: #42b983;
          &::before {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            position: relative;
            margin-right: 2px;
          }
        }
      }
    }
    .contextmenu {
      margin: 0;
      background: #fff;
      z-index: 3000;
      position: absolute;
      list-style-type: none;
      padding: 5px 0;
      border-radius: 4px;
      font-size: 12px;
      font-weight: 400;
      color: #333;
      box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
      li {
        margin: 0;
        padding: 7px 16px;
        cursor: pointer;
        &:hover {
          background: #eee;
        }
      }
    }
  }
  </style>
  
  <style lang="scss">
  //reset element css of el-icon-close
  .tags-view-wrapper {
    .tags-view-item {
      .el-icon-close {
        width: 16px;
        height: 16px;
        vertical-align: 2px;
        border-radius: 50%;
        text-align: center;
        transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
        transform-origin: 100% 50%;
        &:before {
          transform: scale(0.6);
          display: inline-block;
          vertical-align: -3px;
        }
        &:hover {
          background-color: #b4bccc;
          color: #fff;
          width: 12px !important;
          height: 12px !important;
        }
      }
    }
  }
  </style>